#ifndef A_H
#define A_H

#include <cstdlib>
#include <set>
#include "location.h"
#include "direction.h"


class A
{
    public: A(const Location& start, const Location& end);

        void find();
    protected:
    private:
        typedef int step;
        struct Node
        {
            Node(const Node& node) : loc(node.loc), f(node.f), g(node.g), h(node.h) {}
            Node(const Location& _loc, step _f = 0, step _g = 0, step _h = 0) : loc(_loc), f(_f), g(_g), h(_h) {}
            step f;
            step g;
            step h;
            Location loc;

            struct Less : public std::binary_function<Node,Node,bool>{
                bool operator() (const Node& a, const Node& b) const {return (a.f < b.f) || (a.g < b.g) || (a.h < b.h);}
            };

            void move(t_direction direction)
            {
                switch (direction)
                {
                    //TODO: usage map resolution
                    case NORD: --loc.row; break;
                    case WEST: --loc.col; break;
                    case SOUTH: ++loc.row; break;
                    case EAST: ++loc.row; break;
                    default: //TODO: throw exception
                        return;
                }
            }
        };


        friend struct Node;

        typedef std::set<Node, Node::Less > NodeSet;

        void Discover(const Node& node);
        void Discover(const Node& node, t_direction direction);
        bool IsValid(const Node& node) const {return !IsClosed(node);}
        bool IsPathFound() const;
        bool IsClosed(const Node& node) const;

        NodeSet m_open_nodes;
        NodeSet m_close_nodes;

        Location m_start;
        Location m_end;

        step m_step_count;

};

#endif // A_H
